package net.atomarrow.controllers;

import net.atomarrow.action.AtomarrowRequest;
import net.atomarrow.annotation.Inject;
import net.atomarrow.bean.Pager;
import net.atomarrow.bean.ServiceResult;
import net.atomarrow.bean.UploadFile;
import net.atomarrow.ioc.ActionContext;
import net.atomarrow.render.CaptchaRender;
import net.atomarrow.render.Render;
import net.atomarrow.render.RenderFactory;
import net.atomarrow.util.JsonUtil;
import net.atomarrow.util.StringUtil;

import javax.servlet.http.Cookie;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import javax.servlet.http.HttpSession;
import java.io.InputStream;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * 控制层
 *
 * @author Michael
 */
public class Controller {
    @Inject
    private ParamParser paramParser;

    @Inject
    private RenderFactory renderFactory;


    public ActionContext getActionContext() {
        return ActionContext.getContext();
    }

    public HttpServletRequest getRequest() {
        return getActionContext().getRequest();
    }

    public HttpServletResponse getResponse() {
        return getActionContext().getResponse();
    }

    /**
     * 上传文件 使用全局默认地址 如果没有配置就是Webroot根目录
     *
     * @param name
     * @return
     */
    public UploadFile getFile(String name) {
        return paramParser.getFile(name);
    }

    /**
     * 上传文件 使用全局默认地址 如果没有配置就是Webroot根目录
     *
     * @return
     */
    public UploadFile getFile() {
        return paramParser.getFile();
    }

    /**
     * 上传多文件 使用全局默认地址 如果没有配置就是Webroot根目录
     *
     * @return
     */
    public List<UploadFile> getFiles() {
        return paramParser.getFiles();
    }

    /**
     * 上传文件 使用自定义保存地址 如果没有配置就是Webroot根目录
     *
     * @param name
     * @param uploadPath
     * @return
     */
    public UploadFile getFile(String name, String uploadPath) {
        return paramParser.getFile(name, uploadPath);
    }

    /**
     * 上传多文件 使用自定义保存地址 如果没有配置就是Webroot根目录
     *
     * @param uploadPath
     * @return
     */
    public List<UploadFile> getFiles(String uploadPath) {
        return paramParser.getFiles(uploadPath);
    }

    public String getParamString(String name) {
        return paramParser.parseRequestString(name, getRequest());
    }

    public String getParamString(String name, String defaultValue) {
        String value = getParamString(name);
        return value == null ? defaultValue : value;
    }

    public Date getParamDate(String name) {
        return paramParser.parseRequestDate(name, getRequest());
    }

    public Date getParamTime(String name) {
        return paramParser.parseRequestTime(name, getRequest());
    }

    public Date getParamDate(String name, Date defaultDate) {
        Date date = paramParser.parseRequestDate(name, getRequest());
        if (date == null) {
            return defaultDate;
        }
        return date;
    }

    public Date getParamDate(String name, String partten) {
        return paramParser.parseRequestDate(name, partten, getRequest());
    }

    public Integer getParamInteger(String name) {
        return paramParser.parseRequestInteger(name, getRequest());
    }

    public Integer getParamInteger(String name, Integer defaultValue) {
        Integer value = getParamInteger(name);
        return value == null ? defaultValue : value;
    }

    public Double getParamDouble(String name) {
        return paramParser.parseRequestDouble(name, getRequest());
    }

    public Double getParamDouble(String name, Double defaultValue) {
        Double value = getParamDouble(name);
        return value == null ? defaultValue : value;
    }

    public Long getParamLong(String name) {
        return paramParser.parseRequestLong(name, getRequest());
    }

    public Boolean getParamBoolean(String name) {
        return paramParser.parseRequestBoolean(name, getRequest());
    }

    public Boolean getParamBoolean(String name, Boolean defaultValue) {
        Boolean value = getParamBoolean(name);
        return value == null ? defaultValue : value;
    }

    public String getParamString(int index) {
        return paramParser.parseRequestString(index, getRequest());
    }

    public String getParamString(int index, String defaultValue) {
        String value = getParamString(index);
        return value == null ? defaultValue : value;
    }

    public Integer getParamInteger(int index) {
        return paramParser.parseRequestInteger(index, getRequest());
    }

    public Integer getParamInteger(int index, Integer defaultValue) {
        Integer value = getParamInteger(index);
        return value == null ? defaultValue : value;
    }

    public Boolean getParamBoolean(int index) {
        return paramParser.parseRequestBoolean(index, getRequest());
    }

    public <T> T getParamObject(String name, Class<T> clazz) {
        return paramParser.parseRequestObject(name, clazz, (AtomarrowRequest) getRequest());
    }

    public String[] getParamArray(String name) {
        return paramParser.parseRequestArray(name, null, String.class, (AtomarrowRequest) getRequest());
    }

    public String getParamArrayString(String name, String separator) {
        return StringUtil.arrayToString(getParamArray(name), separator);
    }

    public Integer[] getParamIntArray(String name) {
        return paramParser.parseRequestArray(name, null, Integer.class, (AtomarrowRequest) getRequest());
    }

    public Object getParamObject(String name) {
        return paramParser.parseRequestObject(name, Object.class, (AtomarrowRequest) getRequest());
    }

    public <T> List<T> getParamList(String name, Class<T> clazz) {
        return paramParser.parseRequestList(name, null, clazz, (AtomarrowRequest) getRequest());
    }

    public Object getAttr(String name) {
        return getRequest().getAttribute(name);
    }

    public void setAttr(String name, Object obj) {
        getRequest().setAttribute(name, obj);
    }

    public void putSession(String name, Object obj) {
        getSession().setAttribute(name, obj);
    }

    public <T> T getFromSession(String name) {
        return (T) getSession().getAttribute(name);
    }

    public HttpSession getSession() {
        return getRequest().getSession();
    }

    /**
     * 跳转外网
     *
     * @param url
     * @return
     */
    public Render renderRedirect(String url) {
        return renderFactory.createRedirectRender(url);
    }

    public Render renderJsp(String path) {
        return renderFactory.createJspRender(path, false);
    }

    public Render renderJspRedirect(String path) {
        return renderFactory.createJspRender(path, true);
    }

    public Render renderAction(String Action) {
        return renderFactory.createActionRender(Action, false);
    }

    public Render renderActionRedirect(String Action) {
        return renderFactory.createActionRender(Action, true);
    }

    public Render renderJson(String data) {
        return renderFactory.createJsonRender(data);
    }
    /**
     * json操作成功
     *
     * @
     */
    public Render renderJsonSuccess() {
        return renderJsonSuccess(null);
    }


    /**
     * json操作成功
     *
     * @
     */
    public Render renderJsonSuccess(String msg) {
        return renderJsonData(new ServiceResult(true, null, msg));
    }

    /**
     * json操作失败
     *
     * @param msg
     *            @
     */
    public Render renderJsonFail(String msg) {
        return renderJsonData(new ServiceResult(false, null, msg));
    }
    /**
     * json格式返回
     *
     * @
     */
    public Render renderJsonData(Object obj) {
        return renderJsonData(obj, null);
    }
    /**
     * json格式返回
     *
     * @
     */
    public Render renderJsonData(Object obj, Pager pager) {
        if (obj instanceof ServiceResult) {
            ServiceResult serviceResult = (ServiceResult) obj;
            if (pager != null) {
                serviceResult.setPager(pager);
            }
            return renderJsonServiceResult(serviceResult);
        } else {
            return renderJsonServiceResult(new ServiceResult(true, obj, null, pager));
        }
    }
    /**
     * json格式返回
     *
     * @
     */
    public Render renderJsonDataWith(Object obj, String... param) {
        if (obj instanceof ServiceResult) {
            return renderJson(JsonUtil.toJsonWith(obj, param));
        }
        return renderJson(JsonUtil.toJsonWith(new ServiceResult(true, obj,
                null), param));
    }

    /**
     * json格式返回
     *
     * @
     */
    public Render renderJsonDataWith(Object obj, Pager pager, String... param) {
        if (pager != null && param != null) {
            int len = param.length;
            String[] p = new String[len + 6];
            for (int i = 0; i < param.length; i++) {
                p[i] = param[i];
            }
            p[len] = "pager";
            p[len + 1] = "dataTotal";
            p[len + 2] = "pageTotal";
            p[len + 3] = "offset";
            p[len + 4] = "pageSize";
            p[len + 5] = "currentPage";
            param = p;
        }
        return renderJson(JsonUtil.toJsonWith(new ServiceResult(true, obj,
                null, pager), param));
    }

    /**
     * json格式返回
     *
     * @
     */
    public Render renderJsonDataWithOut(Object obj, String... param) {
        return renderJson(JsonUtil.toJsonWithOut(new ServiceResult(true,
                obj, null), param));
    }

    /**
     * json格式返回
     *
     * @
     */
    public Render renderJsonDataWithOut(Object obj, Pager pager, String... param) {
        return renderJson(JsonUtil.toJsonWithOut(new ServiceResult(true,
                obj, null, pager), param));
    }
    /**
     * json格式返回
     *
     * @
     */
    public Render renderJsonServiceResult(ServiceResult result) {
        Object returnResult = result;
        if (result.isWithMode()) {
            return renderJson(JsonUtil.toJsonWith(returnResult,
                    result.getWithParams()));
        } else if (result.isWithoutMode()) {
            return renderJson(JsonUtil.toJsonWithOut(returnResult,
                    result.getWithoutParams()));
        }
        return renderJson(JsonUtil.toJson(returnResult));
    }


    public Render renderHtml(String htmlText) {
        return renderFactory.createHtmlRender(htmlText);
    }

    public Render renderText(String text) {
        return renderFactory.createTextRender(text);
    }

    public Render renderError(String text) {
        return renderFactory.createErrorRender(text);
    }

    public Render renderXml(String xmlText) {
        return renderFactory.createXmlRender(xmlText);
    }

    public Render renderFile(String fileName, InputStream is) {
        return renderFactory.createFileRender(fileName, is);
    }

    public Render renderFtl(String templateName) {
        return renderFactory.createFreemarkerRender(templateName);
    }

    public Render renderImg(InputStream is) {
        return renderFactory.createImgRender(is);
    }

    public Render renderImg(InputStream is, Integer width, Integer height) {
        return renderFactory.createImgRender(is, width, height);
    }

    /**
     * 验证码 render
     *
     * @
     */
    public Render renderCaptcha(int width, int height, int count) {
        return new CaptchaRender().setAttr(CaptchaRender.WIDTH, width).setAttr(CaptchaRender.HEIGHT, height).setAttr(CaptchaRender.COUNT, count);
    }

    /**
     * 验证码 render
     *
     * @
     */
    public Render renderCaptcha() {
        return renderCaptcha(130, 40, 4);
    }

    /**
     * 验证码 验证
     *
     * @
     */
    public boolean checkCaptcha(String code) {
        String cacode = (String) getSession().getAttribute(CaptchaRender.SESSION_CAPTCHACODE);
        if (StringUtil.isBlank(cacode) || StringUtil.isBlank(code)) {
            return false;
        }
        return cacode.equals(code);
    }

    public void setCookie(Cookie cookie) {
        getResponse().addCookie(cookie);
    }

    public void setCookie(String key, String value) {
        Cookie cookie = new Cookie(key, value);
        setCookie(cookie);
    }

    public void setCookie(String key, String value, int expiry) {
        Cookie cookie = new Cookie(key, value);
        cookie.setMaxAge(expiry);
        cookie.setPath("/");
        setCookie(cookie);
    }

    public Cookie getCookie(String key) {
        Cookie[] cookies = getRequest().getCookies();
        if (null != cookies) {
            for (Cookie cookie : cookies) {
                if (cookie.getName().equals(key)) {
                    return cookie;
                }
            }
        }
        return null;
    }

    public String getCookieValue(String key) {
        Cookie cookie = getCookie(key);
        if (cookie == null) {
            return null;
        }
        return cookie.getValue();
    }
}
